/*  
   File Browser for SalesForce
   Copyright (c) 2009  Daniel Jordan
  
   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace SFFileBrowser
{
    public partial class FormMain : Form
    {
        SForceAttachmentManager sforce = null;

        private string programName="File Browser for SalesForce";

        public FormMain()
        {
            InitializeComponent();
            
            
          
        }

        private void login()
        {

            frmLogin login = new frmLogin();
            int failMax = 3;


            for (int i = 0; i < failMax; i++)
            {
                login.ClearPassword();
                login.ShowDialog(this);
                
                
                if (login.UserName.Length == 0 || login.Password.Length == 0) return;

                sforce = new SForceAttachmentManager();

                try
                {
                    sforce.login(login.UserName, login.Password, login.Token);
                    break;
                }
                catch (SForceAttachmentManagerException ex)
                {
                    MessageBox.Show("Unable to login. " + ex.Message, "File Browser for SalesForce");
                    
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Unable to login. " + ex.Message,"File Browser for SalesForce");
                   
                }
            }

            if (sforce.LoggedIn)
            {
                login.saveSettings();
                this.loginToolStripMenuItem.Enabled = false;
                this.Text = this.Text + " - " + sforce.UserName;
                if (sforce.UserOrganization != null && sforce.UserOrganization.Length > 0)
                {
                    this.Text = this.Text + " (" + sforce.UserOrganization + ")";
                }

                fillTree();
            }
            else
            {
                //login was not successful
                this.Close();
                
            }
            
        }


        private void fillTree()
        {
            try
            {
                this.Cursor = Cursors.WaitCursor;
                sforce.Users = sforce.GetUsers();
                fillTreeAccounts();
                fillTreeCampaigns();
                fillTreeProducts();
                fillTreeSolutions();
                fillTreeDocumentFolders();
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }


        }

        private void fillTreeProducts()
        {
            if (Properties.Settings.Default.Display_Product == false) return;

            SForceAttachmentFolders accounts = sforce.getProducts();

            TreeNode nodeAccounts = new TreeNode("Products");

            treeFolders.Nodes.Add(nodeAccounts);

            foreach (SForceAttachmentFolder account in accounts)
            {
                TreeNode temp = new TreeNode(account.Name);
                temp.Tag = account; 
                nodeAccounts.Nodes.Add(temp);
            }
        }


        private void fillTreeDocumentFolders()
        {

            if (Properties.Settings.Default.Display_Documents == false) return;


            SForceAttachmentFolders documentFolders = sforce.GetDocumentFolders();

            TreeNode node = new TreeNode("Document Folders");
            SForceAttachmentFolder folder = sforce.CreateGroupingFolder(SForceObjectType.DocumentFolder);
            node.Tag = folder;


            treeFolders.Nodes.Add(node);

            foreach (SForceAttachmentFolder documentFolder in documentFolders)
            {
                TreeNode temp = new TreeNode(documentFolder.Name);
                temp.Tag = documentFolder;
                node.Nodes.Add(temp);
            }
        }

        private void fillTreeAccounts()
        {
            SForceAttachmentFolders accounts = sforce.getAccounts();

            TreeNode nodeAccounts = new TreeNode("Accounts");
            SForceAttachmentFolder folder = sforce.CreateGroupingFolder(SForceObjectType.Account);
            nodeAccounts.Tag = folder;

            
            treeFolders.Nodes.Add(nodeAccounts);

            foreach (SForceAttachmentFolder account in accounts)
            {
                TreeNode temp = new TreeNode(account.Name);
                temp.Tag = account;
                nodeAccounts.Nodes.Add(temp);
            }
        }

        private void fillTreeSolutions()
        {
            if (Properties.Settings.Default.Display_Solution == false) return;

            SForceAttachmentFolders solutions = sforce.GetSolutions();

            TreeNode nodes = new TreeNode("Solutions");
            SForceAttachmentFolder folder = sforce.CreateGroupingFolder(SForceObjectType.Solution);
            nodes.Tag = folder;


            treeFolders.Nodes.Add(nodes);

            foreach (SForceAttachmentFolder item in solutions)
            {
                TreeNode temp = new TreeNode(item.Name);
                temp.Tag = item;
                nodes.Nodes.Add(temp);
            }
        }

        private void fillTreeCampaigns()
        {
            if (Properties.Settings.Default.Display_Campaign == false) return;

            SForceAttachmentFolders solutions = sforce.GetCampaigns();

            TreeNode nodes = new TreeNode("Campaigns");
            SForceAttachmentFolder folder = sforce.CreateGroupingFolder(SForceObjectType.Solution);
            nodes.Tag = folder;


            treeFolders.Nodes.Add(nodes);

            foreach (SForceAttachmentFolder item in solutions)
            {
                TreeNode temp = new TreeNode(item.Name);
                temp.Tag = item;
                nodes.Nodes.Add(temp);
            }
        }

        private void expandNode(TreeNode node)
        {

            if (node != null && node.Tag != null && node.GetNodeCount(true)==0)
            {
                //get SF folder
                SForceAttachmentFolder folder = (SForceAttachmentFolder)node.Tag;

                //expand solution folder
                if (folder.SForceObjectType == SForceObjectType.Solution)
                {
                    node.Nodes.Clear();

                    //create opportunities grouping under account
                    if (Properties.Settings.Default.Display_Solution_Case)
                    {
                        SForceAttachmentFolder tempFolder = sforce.CreateGroupingFolder(SForceObjectType.Case);
                        TreeNode tempNode = new TreeNode();
                        tempNode.Text = "Cases";
                        tempNode.Tag = tempFolder;
                        node.Nodes.Add(tempNode);
                    }
                }

                //expand campaign folder
                if (folder.SForceObjectType == SForceObjectType.Campaign)
                {
                    node.Nodes.Clear();

                    //create opportunities grouping under account
                    if (Properties.Settings.Default.Display_Campaign_Opportunity)
                    {
                        SForceAttachmentFolder tempFolder = sforce.CreateGroupingFolder(SForceObjectType.Opportunity);
                        TreeNode tempNode = new TreeNode();
                        tempNode.Text = "Opportunities";
                        tempNode.Tag = tempFolder;
                        node.Nodes.Add(tempNode);
                    }
                }


                //expand contact folder
                if (folder.SForceObjectType == SForceObjectType.Contact)
                {
                    node.Nodes.Clear();

                    //create opportunities grouping under account
                    if (Properties.Settings.Default.Display_Account_Contact_Case)
                    {
                        SForceAttachmentFolder caseFolder = sforce.CreateGroupingFolder(SForceObjectType.Case);
                        TreeNode tempCases = new TreeNode();
                        tempCases.Text = "Cases";
                        tempCases.Tag = caseFolder;
                        node.Nodes.Add(tempCases);
                    }
                }

                //expand account folder
                if (folder.SForceObjectType == SForceObjectType.Account)
                {
                    node.Nodes.Clear();


                    //create contacts grouping under account
                    if (Properties.Settings.Default.Display_Account_Contact)
                    {
                        SForceAttachmentFolder contactsFolder = sforce.CreateGroupingFolder(SForceObjectType.Contact);
                        TreeNode tempContacts = new TreeNode();
                        tempContacts.Text = "Contacts";
                        tempContacts.Tag = contactsFolder;
                        node.Nodes.Add(tempContacts);
                    }

                    //create contracts grouping under account
                    if (Properties.Settings.Default.Display_Account_Contract)
                    {
                        SForceAttachmentFolder contractsFolder = sforce.CreateGroupingFolder(SForceObjectType.Contract);
                        TreeNode tempContracts = new TreeNode();
                        tempContracts.Text = "Contracts";
                        tempContracts.Tag = contractsFolder;
                        node.Nodes.Add(tempContracts);
                    }

                    //create cases grouping under account
                    if (Properties.Settings.Default.Display_Account_Case)
                    {
                        SForceAttachmentFolder casesFolder = sforce.CreateGroupingFolder(SForceObjectType.Case);
                        TreeNode tempCases = new TreeNode();
                        tempCases.Text = "Cases";
                        tempCases.Tag = casesFolder;
                        node.Nodes.Add(tempCases);
                    }

                    //create opportunities grouping under account
                    if (Properties.Settings.Default.Display_Account_Opportunity)
                    {
                        SForceAttachmentFolder opportunitiesFolder = sforce.CreateGroupingFolder(SForceObjectType.Opportunity);
                        TreeNode tempOpportunities = new TreeNode();
                        tempOpportunities.Text = "Opportunities";
                        tempOpportunities.Tag = opportunitiesFolder;
                        node.Nodes.Add(tempOpportunities);
                    }

                }

                //expand a group folder
                if (folder.SForceObjectType == SForceObjectType.Group_Only)
                {
                    node.Nodes.Clear();

                    TreeNode parentNode = node.Parent;
                    SForceAttachmentFolder parentFolder = (SForceAttachmentFolder) parentNode.Tag;

                    if (folder.GroupType == SForceObjectType.Opportunity)
                    {
                        if (parentFolder.SForceObjectType == SForceObjectType.Account)
                        {
                            //get opportunities for account
                            SForceAttachmentFolders opps = sforce.getOpportunitesForAccount(parentFolder.Id);
                            foreach (SForceAttachmentFolder opp in opps)
                            {
                                TreeNode temp = new TreeNode();
                                temp.Text = opp.Name;
                                temp.Tag = opp;

                                node.Nodes.Add(temp);
                            }
                        }

                        if (parentFolder.SForceObjectType == SForceObjectType.Campaign)
                        {
                            //get opportunities for campaign
                            SForceAttachmentFolders opps = sforce.GetOpportunitesForCampaign(parentFolder.Id);
                            foreach (SForceAttachmentFolder opp in opps)
                            {
                                TreeNode temp = new TreeNode();
                                temp.Text = opp.Name;
                                temp.Tag = opp;

                                node.Nodes.Add(temp);
                            }
                        }
                    }

                    if (folder.GroupType == SForceObjectType.Contact)
                    {
                        if (parentFolder.SForceObjectType == SForceObjectType.Account)
                        {
                            //get contacts for account
                            SForceAttachmentFolders contacts = sforce.getContactsForAccount(parentFolder.Id);

                            foreach (SForceAttachmentFolder contact in contacts)
                            {
                                TreeNode temp = new TreeNode();
                                temp.Text = contact.Name;
                                temp.Tag = contact;
                                node.Nodes.Add(temp);
                            }
                        }

                    }

                    if (folder.GroupType == SForceObjectType.Contract)
                    {
                        if (parentFolder.SForceObjectType == SForceObjectType.Account)
                        {
                            //get contacts for account
                            SForceAttachmentFolders contracts = sforce.getContractsForAccount(parentFolder.Id);

                            foreach (SForceAttachmentFolder contact in contracts)
                            {
                                TreeNode temp = new TreeNode();
                                temp.Text = contact.Name;
                                temp.Tag = contact;
                                node.Nodes.Add(temp);
                            }
                        }

                    }

                    if (folder.GroupType == SForceObjectType.Case)
                    {


                        if (parentFolder.SForceObjectType == SForceObjectType.Solution)
                        {
                            //get cases for solution
                            SForceAttachmentFolders cases = sforce.getCasesForSolutuion(parentFolder.Id);
                            foreach (SForceAttachmentFolder caseitem in cases)
                            {
                                TreeNode temp = new TreeNode();
                                temp.Text = caseitem.Name;
                                temp.Tag = caseitem;
                                node.Nodes.Add(temp);
                            }
                        }

                        if (parentFolder.SForceObjectType == SForceObjectType.Account)
                        {
                            //get cases for account
                            SForceAttachmentFolders cases = sforce.getCasesForAccount(parentFolder.Id);
                            foreach (SForceAttachmentFolder caseitem in cases)
                            {
                                TreeNode temp = new TreeNode();
                                temp.Text = caseitem.Name;
                                temp.Tag = caseitem;
                                node.Nodes.Add(temp);
                            }
                        }
                        if (parentFolder.SForceObjectType == SForceObjectType.Contact)
                        {

                            //get contacts for case
                            string accountID="";
                            if(node.Parent !=null && node.Parent.Parent !=null & node.Parent.Parent.Parent !=null)
                            {
                                SForceAttachmentFolder accountFolder = (SForceAttachmentFolder) node.Parent.Parent.Parent.Tag;
                                accountID=accountFolder.Id;
                            }

                            SForceAttachmentFolders cases = sforce.getCasesForAccountContact(accountID, parentFolder.Id);
                            foreach (SForceAttachmentFolder caseitem in cases)
                            {
                                TreeNode temp = new TreeNode();
                                temp.Text = caseitem.Name;
                                temp.Tag = caseitem;
                                node.Nodes.Add(temp);
                            }
                        }

                    }//end of case group
                   
                }//end of group folders
                
            }
            node.Expand();

        }

      

        private void getFilesNode(TreeNode node)
        {

            listFiles.Clear();

                SForceAttachmentFolder folder = (SForceAttachmentFolder)node.Tag;

                if (folder == null || string.IsNullOrEmpty(folder.Id)) return;

                SForceAttachmentInfos attachments = null;
                if (folder.SForceObjectType == SForceObjectType.DocumentFolder)
                {
                    attachments = sforce.GetDocuments(folder);
                }
                else
                {
                    attachments = sforce.GetAttachments(folder);
                }


                
                foreach (SForceAttachmentInfo attachment in attachments)
                {
                    ListViewItem temp = new ListViewItem(attachment.Name);
                    temp.Tag = attachment;

                    //get icon data
                    FileTypeInformation fileInfo = new FileTypeInformation();

                    int position = attachment.Name.LastIndexOf(".");
                    
                    string type=string.Empty;
                    if (position > 0)
                    {
                         type = attachment.Name.Substring(position);
                    }
                    else
                    {
                        type= attachment.Type;
                    }
                    //check if type is already used


                    if (this.imageListDocuments.Images.ContainsKey(type) == false)
                    {

                        System.Drawing.Icon icon = fileInfo.getIcon(type);

                        if (icon != null)
                        {
                            this.imageListDocuments.Images.Add(type, icon);
                            temp.ImageIndex = this.imageListDocuments.Images.Count - 1;
                        }
                        else
                        {
                            //default icon 
                            temp.ImageIndex = 0;
                        }
                    }
                    else
                    {
                        //icon already exists
                        temp.ImageIndex = this.imageListDocuments.Images.IndexOfKey(type);
                    }
                    listFiles.Items.Add(temp);

                }
            

        }

        private void testToolStripMenuItem_Click(object sender, EventArgs e)
        {
            login();
        }

        private void treeFolders_AfterSelect(object sender, TreeViewEventArgs e)
        {
            //expand the tree item
            try
            {
                this.Cursor = Cursors.WaitCursor;
                this.expandNode(e.Node);
                this.getFilesNode(e.Node);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
            
        }

        private void listFiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            



        }

        private void listFiles_DoubleClick(object sender, EventArgs e)
        {
            if (listFiles.SelectedItems.Count == 0) return;

            this.Cursor = Cursors.WaitCursor;
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected)
                    this.openItem(item);
            }
            this.Cursor = Cursors.Default ;

        }

        private void printItem(ListViewItem item)
        {
 
            SForceAttachmentInfo info = (SForceAttachmentInfo)item.Tag;
            byte[] data = sforce.GetAttachment(info);


            int position = info.Name.LastIndexOf(".");
            string type = info.Name.Substring(position);


            string directory = this.getDataDirectory();
            string filename = directory + info.Id + info.Name;

            FileTypeInformation fileinfo = new FileTypeInformation();
            string program = fileinfo.getPrintProgram(type);

            if (program != null && program.Length > 0)
            {

                System.Diagnostics.Process process = new System.Diagnostics.Process();
                process.StartInfo.UseShellExecute = true;
                process.StartInfo.FileName =program +"  "+ filename;
                process.Start();

            }
        }

        private void openItem(ListViewItem item)
        {

            SForceAttachmentInfo info = (SForceAttachmentInfo)item.Tag;
            byte[] data = sforce.GetAttachment(info);



            string directory = this.getDataDirectory();
            string filename = directory + info.Id + info.Name;

            //save bytes as file
            this.saveFile(filename, data);

            //open the file with a viewer
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo.UseShellExecute = true;
            process.StartInfo.FileName = filename;
            process.Start();
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmOptions form = new frmOptions();
            form.ShowDialog(this);

            //update settings for display
            string listType = Properties.Settings.Default.Display_FileListType;
            switch (listType)
            {
                case "Large Icon":
                    this.listFiles.View = View.LargeIcon;
                    break;

                case "Small Icon":
                    this.listFiles.View = View.SmallIcon;
                    break;

                case "List":
                    this.listFiles.View = View.List;
                    break;

                case "Detail":
                    this.listFiles.View = View.Details ;
                    break;
            }

        }


        private void saveFile(string filename, byte[] data)
        {

           FileStream stream = new FileStream(filename,FileMode.Create);
           stream.Write(data, 0, data.Length);
           stream.Close();

           return;

        }

        private string copyItem(ListViewItem item, string destinationPath)
        {
            SForceAttachmentInfo info = (SForceAttachmentInfo)item.Tag;
            byte[] data = sforce.GetAttachment(info);

            //save bytes as file
             this.saveFile(destinationPath +  info.Name, data);
            return "";
        }

        private void toolStripButtonOpen_Click(object sender, EventArgs e)
        {

            this.Cursor = Cursors.WaitCursor;
            //open each file that is selected
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected)
                    this.openItem(item);
            }
            this.Cursor = Cursors.Default;
        }

        private void toolStripButtonCopy_Click(object sender, EventArgs e)
        {

            if (this.listFiles.SelectedItems.Count == 0) return;
            
            //choose destination
            
            
            this.folderBrowserDialog.ShowDialog(this);
            string directory = this.folderBrowserDialog.SelectedPath;


            //display progress screen

            //copy each file that is selected
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected) this.copyItem(item, directory);
                    
            }

            //close progress screen

        }

        private void toolStripButtonPrint_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected) this.printItem(item);

            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox about = new AboutBox();
            about.ShowDialog(this);
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            this.Show();
            login();
        }

        private void contextMenu_lst_Opening(object sender, CancelEventArgs e)
        {
            
            try
            {
                if (this.listFiles.Items.Count == 0)
                {
                    this.menuItemCopy.Enabled = false;
                    this.menuOpen.Enabled = false;
                    this.menuPrint.Enabled = false;

                }
                else
                {
                    this.menuItemCopy.Enabled = true;
                    this.menuOpen.Enabled = true;
                    this.menuPrint.Enabled = true;

                }
            }
            catch
            {
            }
        }

        private void menuOpen_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            //open each file that is selected
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected)
                    this.openItem(item);
            }
            this.Cursor = Cursors.Default;
        }

        private void menuPrint_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected) this.printItem(item);

            }
            this.Cursor = Cursors.Default;

        }

        private void menuItemCopy_Click(object sender, EventArgs e)
        {
            //choose destination
            DialogResult  result =this.folderBrowserDialog.ShowDialog(this);

            if (result == DialogResult.Cancel) return;
            string directory = this.folderBrowserDialog.SelectedPath;


            //display progress screen

            this.Cursor = Cursors.WaitCursor;
            //copy each file that is selected
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected) this.copyItem(item, directory);

            }
            this.Cursor = Cursors.Default;
            //close progress screen

        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //end the program
            Application.Exit();
        }

        private void menuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private string getDataDirectory()
        {
            string directory = null;
            try
            {       
                directory = Properties.Settings.Default.Cache_Path;

                try
                {
                    DirectoryInfo directoryInfo = new DirectoryInfo(directory);

                    if (directoryInfo.Exists)
                    {
                        return directory;

                    }
                }
                catch { }
                
                if (string.IsNullOrEmpty(directory))
                {
                    DirectoryInfo appDataDirectory = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
                    DirectoryInfo programDataDirectory = appDataDirectory.CreateSubdirectory(programName);
                    if (programDataDirectory.Exists == false) programDataDirectory.Create();
                    
                    DirectoryInfo cacheDirectory = programDataDirectory.CreateSubdirectory("cache");
                    if (cacheDirectory.Exists == false) cacheDirectory.Create();
                    //directory = Environment.SpecialFolder.ApplicationData.ToString();
                    directory = cacheDirectory.ToString();

                    
                }
                if (directory.Substring(directory.Length - 1, 1) != @"\")
                {
                    directory = directory + @"\";

                }

            }
            catch
            {
                directory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                if (directory.Substring(directory.Length - 1, 1) != @"\")
                {
                    directory = directory + @"\";

                }
            }
            return directory;
        }

        private void menuProperties_Click(object sender, EventArgs e)
        {
            //copy each file that is selected
            foreach (ListViewItem item in this.listFiles.Items)
            {
                if (item.Selected)
                {
                    //display properties
                    frmProperties properties = new frmProperties();
                    SForceAttachmentInfo info = (SForceAttachmentInfo)item.Tag;

                    properties.AttachmentInfo = info;
                    properties.Users = sforce.Users;
                    properties.UpdateDisplay();

                    properties.Show(this);

                }

            }


        }
    }
}